﻿/// Copyright © 2013 Microsoft Corporation. 
/// This project is released under the Microsoft Public License (MS-PL)
///
namespace DataMorph.Processing
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Web.Script.Serialization;

    using DataMorph.Common.Storage;

    using Microsoft.Practices.Unity;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Queue;

    public class ProgressQueue : IProgressQueue
    {
        private readonly CloudQueueClient queueClient;

        private readonly CloudQueue queueReference;

        private readonly OperationContext operationContext;

        private readonly QueueRequestOptions queueRequestOptions;

        [InjectionConstructor]
        public ProgressQueue(ICloudStorageAccount cloudStorageAccount) : this(cloudStorageAccount, 32)
        {
        }

        public ProgressQueue(ICloudStorageAccount cloudStorageAccount, int workBatchSize)
        {
            this.BatchSize = workBatchSize > 32 ? 32 : workBatchSize;

            this.queueClient = cloudStorageAccount.CreateCloudQueueClient();
            this.queueReference = this.queueClient.GetQueueReference(Settings.ProgressQueueName);
            this.queueReference.CreateIfNotExists();

            this.operationContext = new OperationContext();
            this.queueRequestOptions = new QueueRequestOptions
            {
                MaximumExecutionTime = TimeSpan.FromMinutes(3),
                RetryPolicy = DataMorphGlobalRetryPolicy.NewPolicy
            };

            this.queueReference.CreateIfNotExists(this.queueRequestOptions, this.operationContext);            
        }

        public int BatchSize { get; private set; }

        public void AddProgressReport(FileProcessedMessage message)
        {
            var jsonSerializer = new JavaScriptSerializer();
            var cloudQueueMessage = new CloudQueueMessage(jsonSerializer.Serialize(message));
            this.queueReference.AddMessage(cloudQueueMessage);
        }

        public void DeleteProgressReport(FileProcessedMessage message)
        {
            try
            {
                this.queueReference.DeleteMessage(
                                        message.GetMessageReference(),
                                        new QueueRequestOptions
                                        {
                                            RetryPolicy = DataMorphGlobalRetryPolicy.NewPolicy
                                        });
            }
            catch (Exception e)
            {
                Trace.TraceError("An error occured while deleting message: {0}", e.ToString());
            }
        }

        public IEnumerable<FileProcessedMessage> GetProgressReports()
        {
            var messages = this.queueReference.GetMessages(
                                                    this.BatchSize,
                                                    TimeSpan.FromMinutes(1),
                                                    this.queueRequestOptions,
                                                    this.operationContext);

            var messageList = new List<FileProcessedMessage>();
            var jsonSerializer = new JavaScriptSerializer();
            foreach (var cloudQueueMessage in messages)
            {
                var fileProcessedMessage = jsonSerializer.Deserialize<FileProcessedMessage>(cloudQueueMessage.AsString);
                fileProcessedMessage.SetMessageReference(cloudQueueMessage);
                messageList.Add(fileProcessedMessage);
            }

            return messageList;
        }
    }
}